from flask import Flask, request, jsonify, session
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime, date, time
from decimal import Decimal
from sqlalchemy import func
import os
from models import db, Employee, AttendanceRecord, PayrollRecord, User
from cli import register_commands

def create_app():
    """创建Flask应用"""
    app = Flask(__name__)
    
    # 配置
    app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-production')
    
    # 数据库配置 - 支持多种数据库
    database_url = os.environ.get('DATABASE_URL')
    if not database_url:
        # 检查是否有MySQL可用，否则使用SQLite
        try:
            import mysql.connector
            # 尝试连接MySQL
            test_conn = mysql.connector.connect(
                host='localhost',
                user='root',
                password='password',
                database='ems_db'
            )
            test_conn.close()
            database_url = 'mysql+mysqlconnector://root:password@localhost/ems_db'
            print("使用MySQL数据库")
        except:
            database_url = 'sqlite:///ems.db'
            print("MySQL不可用，使用SQLite数据库")
    
    app.config['SQLALCHEMY_DATABASE_URI'] = database_url
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    
    # MySQL特定配置
    if 'mysql' in database_url:
        app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
            'pool_pre_ping': True,
            'pool_recycle': 300,
        }
    
    # 初始化扩展
    db.init_app(app)
    CORS(app, supports_credentials=True)
    
    # 注册CLI命令
    register_commands(app)
    
    # 错误处理
    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({'error': 'Bad request', 'message': str(error)}), 400
    
    @app.errorhandler(404)
    def not_found(error):
        return jsonify({'error': 'Not found', 'message': str(error)}), 404
    
    @app.errorhandler(500)
    def internal_error(error):
        db.session.rollback()
        return jsonify({'error': 'Internal server error', 'message': str(error)}), 500

    # 认证相关路由
    @app.route('/api/login', methods=['POST'])
    def login():
        """用户登录"""
        try:
            data = request.get_json()
            if not data or not data.get('username') or not data.get('password'):
                return jsonify({'error': '用户名和密码不能为空'}), 400
            
            user = User.query.filter_by(username=data['username']).first()
            if user and check_password_hash(user.password_hash, data['password']):
                session['user_id'] = user.id
                session['username'] = user.username
                return jsonify({
                    'isAuthenticated': True,
                    'username': user.username
                })
            else:
                return jsonify({'error': '用户名或密码错误'}), 401
        except Exception as e:
            return jsonify({'error': '登录失败', 'message': str(e)}), 500

    @app.route('/api/logout', methods=['POST'])
    def logout():
        """用户登出"""
        session.clear()
        return jsonify({'message': '登出成功'})

    @app.route('/api/check_auth', methods=['GET'])
    def check_auth():
        """检查认证状态"""
        if 'user_id' in session:
            return jsonify({
                'isAuthenticated': True,
                'username': session.get('username')
            })
        return jsonify({'isAuthenticated': False})

    # 员工管理路由
    @app.route('/api/employees', methods=['GET'])
    def get_employees():
        """获取所有员工"""
        try:
            employees = Employee.query.order_by(Employee.created_at.desc()).all()
            return jsonify([employee.to_dict() for employee in employees])
        except Exception as e:
            return jsonify({'error': '获取员工列表失败', 'message': str(e)}), 500

    @app.route('/api/employees', methods=['POST'])
    def add_employee():
        """添加新员工"""
        try:
            data = request.get_json()
            if not data:
                return jsonify({'error': '请求数据不能为空'}), 400
            
            # 验证必填字段
            required_fields = ['name', 'email', 'position', 'department', 'hireDate', 'salary']
            for field in required_fields:
                if field not in data or not data[field]:
                    return jsonify({'error': f'{field} 字段不能为空'}), 400
            
            # 检查邮箱是否已存在
            if Employee.query.filter_by(email=data['email']).first():
                return jsonify({'error': '该邮箱已被使用'}), 400
            
            # 创建新员工
            employee = Employee(
                name=data['name'],
                email=data['email'],
                position=data['position'],
                department=data['department'],
                hire_date=datetime.strptime(data['hireDate'], '%Y-%m-%d').date(),
                salary=Decimal(str(data['salary'])),
                avatar=data.get('avatar', 'https://via.placeholder.com/150'),
                job_description=data.get('jobDescription', '')
            )
            
            db.session.add(employee)
            db.session.commit()
            
            return jsonify({'id': employee.id, 'message': '员工添加成功'}), 201
        except ValueError as e:
            return jsonify({'error': '日期格式错误'}), 400
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': '添加员工失败', 'message': str(e)}), 500

    @app.route('/api/employees/<int:employee_id>', methods=['PUT'])
    def update_employee(employee_id):
        """更新员工信息"""
        try:
            employee = Employee.query.get_or_404(employee_id)
            data = request.get_json()
            
            if not data:
                return jsonify({'error': '请求数据不能为空'}), 400
            
            # 更新字段
            if 'name' in data:
                employee.name = data['name']
            if 'email' in data:
                # 检查邮箱是否被其他员工使用
                existing = Employee.query.filter_by(email=data['email']).first()
                if existing and existing.id != employee_id:
                    return jsonify({'error': '该邮箱已被其他员工使用'}), 400
                employee.email = data['email']
            if 'position' in data:
                employee.position = data['position']
            if 'department' in data:
                employee.department = data['department']
            if 'hireDate' in data:
                employee.hire_date = datetime.strptime(data['hireDate'], '%Y-%m-%d').date()
            if 'salary' in data:
                employee.salary = Decimal(str(data['salary']))
            if 'avatar' in data:
                employee.avatar = data['avatar']
            if 'jobDescription' in data:
                employee.job_description = data['jobDescription']
            
            employee.updated_at = datetime.utcnow()
            db.session.commit()
            
            return jsonify({'message': '员工信息更新成功'})
        except ValueError as e:
            return jsonify({'error': '日期格式错误'}), 400
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': '更新员工信息失败', 'message': str(e)}), 500

    @app.route('/api/employees/<int:employee_id>', methods=['DELETE'])
    def delete_employee(employee_id):
        """删除员工"""
        try:
            employee = Employee.query.get_or_404(employee_id)
            db.session.delete(employee)
            db.session.commit()
            return jsonify({'message': '员工删除成功'})
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': '删除员工失败', 'message': str(e)}), 500

    # 考勤管理路由
    @app.route('/api/attendance', methods=['GET'])
    def get_attendance():
        """获取考勤记录"""
        try:
            attendance = AttendanceRecord.query.order_by(AttendanceRecord.date.desc()).all()
            return jsonify([record.to_dict() for record in attendance])
        except Exception as e:
            return jsonify({'error': '获取考勤记录失败', 'message': str(e)}), 500

    @app.route('/api/attendance', methods=['POST'])
    def add_attendance():
        """添加考勤记录"""
        try:
            data = request.get_json()
            if not data:
                return jsonify({'error': '请求数据不能为空'}), 400
            
            # 验证必填字段
            required_fields = ['employeeId', 'date', 'status']
            for field in required_fields:
                if field not in data or not data[field]:
                    return jsonify({'error': f'{field} 字段不能为空'}), 400
            
            # 检查员工是否存在
            employee = Employee.query.get(data['employeeId'])
            if not employee:
                return jsonify({'error': '员工不存在'}), 404
            
            # 检查是否已有该日期的考勤记录
            record_date = datetime.strptime(data['date'], '%Y-%m-%d').date()
            existing = AttendanceRecord.query.filter_by(
                employee_id=data['employeeId'],
                date=record_date
            ).first()
            if existing:
                return jsonify({'error': f'该员工在{data["date"]}已有考勤记录'}), 400
            
            # 创建考勤记录
            attendance = AttendanceRecord(
                employee_id=data['employeeId'],
                date=datetime.strptime(data['date'], '%Y-%m-%d').date(),
                status=data['status'],
                clock_in=datetime.strptime(data['clockIn'], '%H:%M').time() if data.get('clockIn') else None,
                clock_out=datetime.strptime(data['clockOut'], '%H:%M').time() if data.get('clockOut') else None
            )
            
            db.session.add(attendance)
            db.session.commit()
            
            return jsonify({'id': attendance.id, 'message': '考勤记录添加成功'}), 201
        except ValueError as e:
            return jsonify({'error': '日期或时间格式错误'}), 400
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': '添加考勤记录失败', 'message': str(e)}), 500

    # 工资管理路由
    @app.route('/api/payroll', methods=['GET'])
    def get_payroll():
        """获取工资记录"""
        try:
            payroll = PayrollRecord.query.order_by(PayrollRecord.created_at.desc()).all()
            return jsonify([record.to_dict() for record in payroll])
        except Exception as e:
            return jsonify({'error': '获取工资记录失败', 'message': str(e)}), 500

    @app.route('/api/payroll', methods=['POST'])
    def add_payroll():
        """添加工资记录"""
        try:
            data = request.get_json()
            if not data:
                return jsonify({'error': '请求数据不能为空'}), 400
            
            # 验证必填字段
            required_fields = ['employeeId', 'payPeriod', 'baseSalary']
            for field in required_fields:
                if field not in data or not data[field]:
                    return jsonify({'error': f'{field} 字段不能为空'}), 400
            
            # 检查员工是否存在
            employee = Employee.query.get(data['employeeId'])
            if not employee:
                return jsonify({'error': '员工不存在'}), 404
            
            # 计算实发工资
            base_salary = Decimal(str(data['baseSalary']))
            bonus = Decimal(str(data.get('bonus', 0)))
            deductions = Decimal(str(data.get('deductions', 0)))
            net_pay = base_salary + bonus - deductions
            
            # 创建工资记录
            payroll = PayrollRecord(
                employee_id=data['employeeId'],
                pay_period=data['payPeriod'],
                base_salary=base_salary,
                bonus=bonus,
                deductions=deductions,
                net_pay=net_pay
            )
            
            db.session.add(payroll)
            db.session.commit()
            
            return jsonify({'id': payroll.id, 'message': '工资记录添加成功'}), 201
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': '添加工资记录失败', 'message': str(e)}), 500

    # 统计信息路由
    @app.route('/api/stats', methods=['GET'])
    def get_stats():
        """获取统计信息"""
        try:
            total_employees = Employee.query.count()
            total_attendance_today = AttendanceRecord.query.filter_by(
                date=date.today()
            ).count()
            total_payroll_this_month = db.session.query(
                func.sum(PayrollRecord.net_pay)
            ).filter(
                PayrollRecord.pay_period.like(f'{datetime.now().year}-{datetime.now().month:02d}%')
            ).scalar() or 0
            
            return jsonify({
                'totalEmployees': total_employees,
                'attendanceToday': total_attendance_today,
                'payrollThisMonth': float(total_payroll_this_month)
            })
        except Exception as e:
            return jsonify({'error': '获取统计信息失败', 'message': str(e)}), 500

    return app

if __name__ == '__main__':
    app = create_app()
    with app.app_context():
        db.create_all()
    app.run(debug=True, host='0.0.0.0', port=5000)